﻿/*
SINACOR - BMF&Bovespa
Arquivo: AlocacaoCoberturaTermo.cs
Criado em: 27-nov-2009 11:59:14
Arquiteto Responsável: RAMelo.7Comm
*/
using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Service.Data;
using System.Data.Common;
using System.Data;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Enum;
using Sinacor.Servico.Bovespa.Alocacao.BusinessEntity;
using Sinacor.Infra.Service.Common;
using Sinacor.Servico.Bovespa.BovespaBase.Util;
using Sinacor.Servico.Bovespa.Alocacao;

namespace Sinacor.Servico.Bovespa.Alocacao.ResourceAccess
{
    /// <summary>
    /// Classe de acesso a dados para atender o contrato de serviços
    /// IAlocacaoCoberturaTermo
    /// </summary>
    public class AlocacaoCarteiraVendaDescoberta : BaseResourceAccess
    {
        #region Construtores
        /// <summary>
        /// Construtor padrão
        /// </summary>
        public AlocacaoCarteiraVendaDescoberta()
            : base(AuthorizationContext.Current.CompanyId)
        {
        }
        #endregion Construtores

        #region Métodos
        /// <summary>
        /// Consulta o os lotes e ordens na qual as ordens que constituem a venda descoberta se encontram.
        /// </summary>
        /// <param name="parameter"></param>
        public List<BusinessEntity.LoteOrdem> ConsultarLotesVendaDescoberta(BusinessEntity.VendaDescoberta parameter)
        {
            List<BusinessEntity.LoteOrdem> response = new List<BusinessEntity.LoteOrdem>();
            
            #region SQL
            StringBuilder sql = new StringBuilder(@"SELECT ");
            sql.AppendLine(@"  B.NR_CONJUNTO NumeroConjunto, ");
            sql.AppendLine(@"  A.NR_SEQORD NumeroOrdem, ");
            sql.AppendLine(@"  A.NR_SUBSEQ NumeroOrdemSubSequencia, ");
            sql.AppendLine(@"  A.DT_DATORD DataOrdem, ");
            sql.AppendLine(@"  C.DT_NEGOCIO DataPregao");
            sql.AppendLine(@"FROM (TORMOVD A INNER JOIN TORCOMI C ON A.DT_DATORD = C.DT_DATORD AND ");
            sql.AppendLine(@"      A.NR_SEQORD = C.NR_SEQORD AND "); 
            sql.AppendLine(@"      A.NR_SUBSEQ = C.NR_SUBSEQ) ");
            sql.AppendLine(@"LEFT JOIN TORDISCONJ B ON B.DT_DATORD = A.DT_DATORD AND ");
            sql.AppendLine(@"      B.NR_SEQORD = A.NR_SEQORD AND  ");
            sql.AppendLine(@"      B.NR_SUBSEQ = A.NR_SUBSEQ ");
            sql.AppendLine(@"      WHERE C.DT_NEGOCIO = :DataPregao AND ");
            sql.AppendLine(@"      A.CD_CLIENTE = :Cliente AND ");
            sql.AppendLine(@"      A.CD_NEGOCIO = :Ativo AND ");
            sql.AppendLine(@"      A.CD_NATOPE = 'V' ");

            #endregion

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "Ativo", DbType.String, parameter.Ativo);

                this.DataBase.AddInParameter(command, "Cliente", DbType.Int32, parameter.Cliente);

                this.DataBase.AddInParameter(command, "DataPregao", DbType.DateTime, parameter.DataPregao);

                response = this.FindAll<BusinessEntity.LoteOrdem>(command,
                   reader =>
                   {
                       BusinessEntity.LoteOrdem item = new BusinessEntity.LoteOrdem();

                       item.DataPregao = reader.GetValue<DateTime?>("DataPregao");
                       item.NumeroConjunto = reader.GetValue<int?>("NumeroConjunto");
                       item.Ordem = new Sinacor.Servico.Bovespa.ManutencaoOrdens.BusinessEntity.ChaveOrdem() { DataOrdem = reader.GetValue<DateTime>("DataOrdem"), NumeroOrdem = reader.GetValue<int>("NumeroOrdem"), NumeroOrdemSubSequencia = reader.GetValue<int>("NumeroOrdemSubSequencia") };
                       return item;
                   });
            }

            return response;
        }

        /// <summary>
        /// Consulta as vendas descobertas na carteira 216, agrupado por ativo e cliente
        ///São exclusas operações do tipo:
        ///- Operações POP ou resultante de Operações POP
        ///- Operações Administrado Concorrente
        ///- Mercados Não Derivativos (OPC, OPV, TER, FUT)
        ///- Clientes que possuam Cliente Custodiante ou Institucional
        ///- Operações direcionadas a Custodiante Externo
        ///- Clientes Broker
        /// </summary>
        /// <param name="parameter"></param>
        public List<BusinessEntity.VendaDescoberta> ConsultarVendasDescobertas216(BusinessEntity.Parameter.FiltroVendaDescoberta parameter)
        {
            List<BusinessEntity.VendaDescoberta> response = new List<BusinessEntity.VendaDescoberta>();

            #region SQL
            StringBuilder sql = new StringBuilder(@"SELECT SUM(DECODE(A.CD_NATOPE,'V',-1,1) * A.QT_QTDESP) AS QuantidadeDescoberta, ");
            sql.AppendLine(@"  SUM(DECODE(A.CD_NATOPE,'V',A.QT_QTDESP,0)) AS QuantidadeTotal, ");
            sql.AppendLine(@"  A.CD_CLIENTE AS Cliente, ");
            sql.AppendLine(@"  A.CD_NEGOCIO AS Ativo,  ");
            sql.AppendLine(@"  A.DT_NEGOCIO AS DataPregao ");
            sql.AppendLine(@"FROM TORCOMI A ");
            sql.AppendLine(@"INNER JOIN TORMOVD B ON B.DT_DATORD = A.DT_DATORD AND ");
            sql.AppendLine(@"      B.NR_SEQORD = A.NR_SEQORD AND ");
            sql.AppendLine(@"      B.NR_SUBSEQ = A.NR_SUBSEQ AND ");
            sql.AppendLine(@"      SUBSTR(CD_CODISI,7,2) != 'PP' ");
            sql.AppendLine(@"INNER JOIN TORNEGD C ON C.CD_BOLSAMOV = A.CD_BOLSAMOV AND ");
            sql.AppendLine(@"      C.DT_PREGAO = A.DT_NEGOCIO AND ");
            sql.AppendLine(@"      C.CD_NEGOCIO = A.CD_NEGOCIO AND ");
            sql.AppendLine(@"      C.CD_NATOPE = A.CD_NATOPE AND ");
            sql.AppendLine(@"      C.NR_NEGOCIO = A.NR_NEGOCIO ");
            sql.AppendLine(@"      LEFT JOIN TORMOVD D ");
            sql.AppendLine(@"      ON D.DT_DATORD = B.DT_DATORD ");
            sql.AppendLine(@"      AND D.NR_SEQORD = B.NR_SEQORD ");
            sql.AppendLine(@"      AND D.NR_SUBSEQ = 0 ");
            sql.AppendLine(@"      AND SUBSTR(D.CD_CODISI,7,2) = 'PP' ");
            sql.AppendLine(@"INNER JOIN TSCCLIBOL E ON E.CD_CLIENTE = A.CD_CLIENTE ");
            sql.AppendLine(@"INNER JOIN TBOMERCAR F ON F.CD_CARLIQ = A.CD_CARLIQ AND ");
            sql.AppendLine(@"      F.CD_ALMERC = C.TP_MERCADO AND ");
            sql.AppendLine(@"      F.CD_NATOPE = A.CD_NATOPE AND ");
            sql.AppendLine(@"      NVL(F.IND_DAYT,'N') = 'S' ");
            sql.AppendLine(@"WHERE D.NR_SEQORD IS NULL AND ");
            sql.AppendLine(@"      A.DT_NEGOCIO = :DataPregao AND ");
            sql.AppendLine(@"      A.CD_CARLIQ = 216 AND ");
            sql.AppendLine(@"      B.IN_ADMIN_CON = 'N' AND ");
            sql.AppendLine(@"INSTR(TO_CHAR(B.TP_ORDEM), '4') = 0 AND ");
            sql.AppendLine(@"       C.TP_MERCADO NOT IN ('OPC', 'OPV', 'TER', 'FUT') AND" );
            sql.AppendLine(@"       (A.CD_USUFIM IS NULL OR A.CD_USUFIM = 0) AND");
            sql.AppendLine(@"       (A.CD_CLIFIM IS NULL OR A.CD_CLIFIM = 0) AND");
            sql.AppendLine(@"       (A.IN_LIQUIDA IS NULL OR TRIM(A.IN_LIQUIDA) = '') AND");
            
            string acessoListaAcessores = new Acesso.BusinessLogic.Acesso().ConsultarListaAssessores("E.CD_ASSESSOR", 0, 9999999);
            sql.AppendLine(acessoListaAcessores);
            
            #endregion

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                if (!String.IsNullOrEmpty(parameter.ApelidoCliente))
                {
                    sql.AppendLine(" AND E.NM_APELIDO = :ApelidoCliente");
                    this.DataBase.AddInParameter(command, "ApelidoCliente", DbType.String, parameter.ApelidoCliente);
                }
                if (parameter.Cliente != null)
                {
                    sql.AppendLine(" AND A.CD_CLIENTE = :Cliente");
                    this.DataBase.AddInParameter(command, "Cliente", DbType.Int32, parameter.Cliente);
                }
                if (!String.IsNullOrEmpty(parameter.Ativo))
                {
                    sql.AppendLine(" AND A.CD_NEGOCIO = :Ativo");
                    this.DataBase.AddInParameter(command, "Ativo", DbType.String, parameter.Ativo);
                }

                this.DataBase.AddInParameter(command, "DataPregao", DbType.DateTime, parameter.DataPregao);

                sql.AppendLine(@" GROUP BY A.CD_CLIENTE, A.CD_NEGOCIO, A.DT_NEGOCIO ");

                command.CommandText = sql.ToString();

                response = this.FindAll<BusinessEntity.VendaDescoberta>(command,
                    reader =>
                    {
                        BusinessEntity.VendaDescoberta item = new BusinessEntity.VendaDescoberta();

                        item.Ativo = reader.GetValue<String>("Ativo");
                        item.Cliente = reader.GetValue<int>("Cliente");
                        item.DataPregao = reader.GetValue<DateTime>("DataPregao");
                        item.QuantidadeDescoberta = reader.GetValue<int>("QuantidadeDescoberta");
                        item.QuantidadeTotal = reader.GetValue<decimal?>("QuantidadeTotal");
                        
                        return item;
                    }
                );
            }

            return response;
        }

        /// <summary>
        /// Obtém a posição atual da carteira geral (216) para um cliente/ativo 
        /// </summary>
        /// <param name="parameter"></param>
        public BusinessEntity.Posicao ObterPosicao216(BusinessEntity.Parameter.FiltroPosicao parameter)
        {
            StringBuilder strSQL = new StringBuilder();
            BusinessEntity.Posicao response = new BusinessEntity.Posicao();

            strSQL.Append(" SELECT SUM(A.QTDE_DISP) AS Quantidade, ");
            strSQL.Append("         C.CD_CLIENTE_ORI AS Cliente, ");
            strSQL.Append("         A.COD_NEG AS Ativo, ");
            strSQL.Append("         216 AS Carteira ");
            strSQL.Append(" FROM TCFPOSI_TOTAL_DIA A ");
            strSQL.Append(" INNER JOIN TCFLOCAL B ON B.COD_LOC = A.COD_LOC AND ");
            strSQL.Append("     B.COD_LOC = (SELECT CD_EMPR_BOLSA FROM TGELOCAL where CD_EMPRESA = :CompanyId AND CD_BOLSA = 1)");
            strSQL.Append(" INNER JOIN TSCRELACATVD C ON C.CD_CLIENTE_DEST = A.COD_CLI AND ");
            strSQL.Append("         C.CD_SISTEMA_DEST = 'CF' AND ");
            strSQL.Append("         C.CD_SISTEMA_ORI = 'BOL' ");
            strSQL.Append(" WHERE A.COD_CART = 21016 AND ");
            strSQL.Append("         C.CD_CLIENTE_ORI = :Cliente AND ");
            strSQL.Append("         A.COD_NEG = :Ativo ");
            strSQL.Append(" GROUP BY C.CD_CLIENTE_ORI ,A.COD_NEG ");


            using (DbCommand command = this.DataBase.GetSqlStringCommand(strSQL.ToString()))
            {
                this.DataBase.AddInParameter(command, "Ativo", DbType.String, parameter.Ativo);
                this.DataBase.AddInParameter(command, "CompanyId", DbType.Int32, AuthorizationContext.Current.CompanyId);                
                this.DataBase.AddInParameter(command, "Cliente", DbType.Int32, parameter.Cliente);
               
                command.CommandText = strSQL.ToString();
                response = this.FindOne<BusinessEntity.Posicao>(command,
                    reader =>
                    {
                        BusinessEntity.Posicao entity = new BusinessEntity.Posicao();

                        entity.Ativo = reader.GetValue<string>("Ativo");
                        entity.Carteira = reader.GetValue<int>("Carteira");
                        entity.CodigoCliente = reader.GetValue<int>("Cliente");
                        entity.Quantidade = reader.GetValue<Decimal?>("Quantidade");

                        return entity;
                    });
            }
            if (response == null)
            {
                return new BusinessEntity.Posicao();
            }
            else
            {
                return response;
            }

            
        }

        /// <summary>
        /// Obtém a posição atual das carteiras 219,274,280,239 para um cliente/ativo
        /// </summary>
        /// <param name="parameter"></param>
        public BusinessEntity.VendaDescoberta ObterPosicoes(BusinessEntity.Parameter.FiltroPosicao parameter)
        {            
            StringBuilder sql = new StringBuilder();
            BusinessEntity.VendaDescoberta response = new BusinessEntity.VendaDescoberta();

            #region SQL
            sql.AppendLine("SELECT NVL(SUM(DECODE(A.COD_CART,21019,A.QTDE_DISP,0)),0) + ");
            sql.AppendLine("(SELECT NVL(SUM(DECODE(C.CD_NATOPE,'V',-1,1) * C.QT_QTDESP),0) FROM TORCOMI C WHERE ");
            sql.AppendLine("  C.CD_NEGOCIO = A.COD_NEG AND C.CD_CLIENTE = E.CD_CLIENTE_ORI AND C.CD_CARLIQ = 219) ");
            sql.AppendLine("PosicaoCarteira219, ");
            
            sql.AppendLine("NVL(SUM(DECODE(A.COD_CART,28010,A.QTDE_DISP,0)),0) + ");
            sql.AppendLine("(SELECT NVL(SUM(DECODE(C.CD_NATOPE,'V',-1,1) * C.QT_QTDESP),0) FROM TORCOMI C WHERE ");
            sql.AppendLine("  C.CD_NEGOCIO = A.COD_NEG AND C.CD_CLIENTE = E.CD_CLIENTE_ORI AND C.CD_CARLIQ = 280) ");
            sql.AppendLine("PosicaoCarteira280, ");
            
            sql.AppendLine("NVL(SUM(DECODE(A.COD_CART,23019,A.QTDE_DISP,0)),0) + ");
            sql.AppendLine("(SELECT NVL(SUM(DECODE(C.CD_NATOPE,'V',-1,1) * C.QT_QTDESP),0) FROM TORCOMI C WHERE ");
            sql.AppendLine("  C.CD_NEGOCIO = A.COD_NEG AND C.CD_CLIENTE = E.CD_CLIENTE_ORI AND C.CD_CARLIQ = 239) ");
            sql.AppendLine("PosicaoCarteira239, ");

            sql.AppendLine("NVL(SUM(DECODE(A.COD_CART,27014,A.QTDE_DISP,0)),0) + ");
            sql.AppendLine("(SELECT NVL(SUM(DECODE(C.CD_NATOPE,'V',-1,1) * C.QT_QTDESP),0) FROM TORCOMI C WHERE ");
            sql.AppendLine("  C.CD_NEGOCIO = A.COD_NEG AND C.CD_CLIENTE = E.CD_CLIENTE_ORI AND C.CD_CARLIQ = 274) ");
            sql.AppendLine("PosicaoCarteira274, ");
            
            sql.AppendLine("E.CD_CLIENTE_ORI Cliente,  ");
            sql.AppendLine("A.COD_NEG Ativo");
            sql.AppendLine("FROM TCFPOSI_TOTAL_DIA A  ");
            sql.AppendLine("INNER JOIN TCFLOCAL B ON B.COD_LOC = A.COD_LOC AND ");
            sql.AppendLine("     B.COD_LOC = (SELECT CD_EMPR_BOLSA FROM TGELOCAL where CD_EMPRESA = :CompanyId AND CD_BOLSA = 1) ");
            sql.AppendLine("INNER JOIN TSCRELACATVD E ON E.CD_CLIENTE_DEST = A.COD_CLI AND ");
            sql.AppendLine("        E.CD_SISTEMA_DEST = 'CF' AND ");
            sql.AppendLine("        E.CD_SISTEMA_ORI = 'BOL' ");
            sql.AppendLine("WHERE A.COD_CART IN (21019,28010,23019,27014) AND ");
            sql.AppendLine("        E.CD_CLIENTE_ORI = :Cliente AND ");
            sql.AppendLine("        A.COD_NEG = :Ativo  ");
            sql.AppendLine("GROUP BY E.CD_CLIENTE_ORI, A.COD_NEG ");

            #endregion

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "Ativo", DbType.String, parameter.Ativo);
                this.DataBase.AddInParameter(command, "Cliente", DbType.Int32, parameter.Cliente);
                this.DataBase.AddInParameter(command, "CompanyId", DbType.Int32, AuthorizationContext.Current.CompanyId);

                command.CommandText = sql.ToString();

                response = this.FindOne<BusinessEntity.VendaDescoberta>
                (
                    command,
                    reader =>
                    {
                        BusinessEntity.VendaDescoberta item = new BusinessEntity.VendaDescoberta();

                        item.PosicaoCarteira219 = reader.GetValue<Decimal>("PosicaoCarteira219");
                        item.PosicaoCarteira239 = reader.GetValue<Decimal>("PosicaoCarteira239");
                        item.PosicaoCarteira274 = reader.GetValue<Decimal>("PosicaoCarteira274");
                        item.PosicaoCarteira280 = reader.GetValue<Decimal>("PosicaoCarteira280");
                        item.Ativo = reader.GetValue<String>("Ativo");
                        item.Cliente = reader.GetValue<int>("Cliente");

                        return item;
                    }
                );
            }

            //Retorna o response preenchido 
            return response;
        }

        /// <summary>
        /// Verifica se o ativo informado como parâmetro de entrada é EX
        /// </summary>
        /// <param name="entity"></param>
        public BusinessEntity.Resultado ValidarAtivoEX(Titulo.BusinessEntity.Titulo entity)
        {
            StringBuilder sql = new StringBuilder();

            BusinessEntity.Resultado resultado = new BusinessEntity.Resultado();

            sql.Append(" DECLARE ");
            sql.Append(" rettype BOOLEAN; ");
            sql.Append(" TEMP_BOOL BOOLEAN; ");            
            sql.Append(" BEGIN ");
            sql.Append(" rettype:= SPCF_PU_PAP.SFCF_CONSUL_PAP_EX(:V_sIsinOrig, :V_nNumDistOrig, :R_dDataEx, :R_nTipoProv, TEMP_BOOL); ");
            sql.Append(" IF TEMP_BOOL THEN :R_BPROVATLSALDO := 1; ELSE :R_BPROVATLSALDO := 0; END IF; ");
            sql.Append(" IF rettype THEN :R_Retorno := 1; ELSE :R_Retorno := 0; END IF; ");
            sql.Append(" END; ");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "V_sIsinOrig", DbType.String, entity.CodigoISIN);
                this.DataBase.AddInParameter(command, "V_nNumDistOrig", DbType.Int32, entity.NumeroDistribuicao);

                this.DataBase.AddOutParameter(command, "R_dDataEx", DbType.Date, 4);
                this.DataBase.AddOutParameter(command, "R_nTipoProv", DbType.Int32, 100);                
                this.DataBase.AddOutParameter(command, "R_BPROVATLSALDO", DbType.Int32, 4);
                this.DataBase.AddOutParameter(command, "R_Retorno", DbType.Int32, 4);

                this.DataBase.ExecuteNonQuery(command);

                if (!Convert.ToBoolean(this.DataBase.GetParameterValue(command , "R_Retorno")))
                {
                    resultado.Sucesso = true;
                    resultado.Valor = (Convert.ToInt32(command.Parameters["R_BPROVATLSALDO"].Value) == 1);
                }
                else
                    resultado.Sucesso = false;                

            }
            return resultado;
        }

        /// <summary>
        /// Verifica se para a chave Cliente,Ativo,Natureza e Pregão existe alguma ordem distribuída
        /// </summary>
        /// <param name="parameter"></param>
        public bool VerificarOrdemDistribuida(BusinessEntity.Parameter.FiltroVerificaOrdemDistribuida parameter)
        {
            bool retorno = false;
            StringBuilder sql = new StringBuilder(@"SELECT COUNT(*) CONT 
                                  FROM TOREXEC A
                                  INNER JOIN TORMOVD B ON B.DT_DATORD = A.DT_DATORD AND
                                        B.NR_SEQORD = A.NR_SEQORD AND
                                        B.NR_SUBSEQ = A.NR_SUBSEQ
                                   WHERE A.DT_NEGOCIO = :DataPregao AND
                                        B.IN_DISTRIB <> 'N' AND
                                        B.CD_LIQFIN = :CodigoCliente AND
                                        B.CD_NATOPE = 'V'");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                if (!String.IsNullOrEmpty(parameter.Ativo))
                {
                    sql.Append(@" AND B.CD_NEGOCIO = :Ativo");
                    this.DataBase.AddInParameter(command, "Ativo", DbType.String, parameter.Ativo);
                }
                else if (!String.IsNullOrEmpty(parameter.CodigoCasamento))
                {
                    sql.Append(@" AND B.CD_CODCAS = :CodigoCasamento");
                    this.DataBase.AddInParameter(command, "CodigoCasamento", DbType.String, parameter.CodigoCasamento);
                }

                this.DataBase.AddInParameter(command, "CodigoCliente", DbType.Int32, parameter.CodigoCliente);
                this.DataBase.AddInParameter(command, "DataPregao", DbType.DateTime, parameter.DataPregao);

                command.CommandText = sql.ToString();                

                if (Convert.ToInt32(this.DataBase.ExecuteScalar(command).ToString()) > 0)
                {
                    retorno = true;
                }
                else
                    retorno = false;

            }

            return retorno;
        }
        
        #endregion Métodos
    }

}
